package com.cjxch.supermybatis.core.tools.query;

import com.cjxch.supermybatis.core.tools.LambdaFunctionUtil;
import com.cjxch.supermybatis.core.tools.SerializableFunction;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * Super-Mybatis查询构造器
 * 
 * @author Caizongyou
 * 
 */
public class SmCriteria {

    private List<Object> criterionList = new ArrayList<Object>();

    private String[] customerRetColumn;

	private SmCriteria() {
    };

    public static class SmCriteriaBuild{
        private List<Object> criterionList = new ArrayList<Object>();
        private String[] customerRetColumn;
        public SmCriteria build(){
            SmCriteria ia = new SmCriteria();
            ia.criterionList = criterionList;
            ia.customerRetColumn = customerRetColumn;
            return ia;
        }
        public SmCriteriaBuild add(Boolean condition, Object c) {
            if(!condition) return this;
            return add(c);
        }

        public SmCriteriaBuild add(Object c) {
            if(c == null) return this;
            criterionList.add(c);
            return this;
        }

        public SmCriteriaBuild customerRetColumn(String customerRetColumn){
            this.customerRetColumn = new String[]{customerRetColumn};
            return this;
        }

        public SmCriteriaBuild customerRetColumn(String[] customerRetColumn){
            this.customerRetColumn = customerRetColumn;
            return this;
        }
    }


    public static class LambdaSmCriteriaBuild<T>{
        private List<Object> criterionList = new ArrayList<Object>();
        private String[] customerRetColumn;
        public SmCriteria build(){
            SmCriteria ia = new SmCriteria();
            ia.criterionList = criterionList;
            ia.customerRetColumn = customerRetColumn;
            return ia;
        }

        /**
         * 相等
         *
         * @param value
         * @return
         */
        public <R extends SerializableFunction<T, Object>> LambdaSmCriteriaBuild<T> eq(Boolean condition, R column, Object value, CriteriaConnector connector) {
            if(!condition) return this;
            SmCriterion sm = new SmCriterion(LambdaFunctionUtil.getFieldName(column), value, CriteriaType.eq, connector);
            criterionList.add(sm);
            return this;
        }

        /**
         * 相等
         *
         * @param value
         * @return
         */
        public <R extends SerializableFunction<T, Object>> LambdaSmCriteriaBuild<T> ge(Boolean condition, R column, Object value, CriteriaConnector connector) {
            if(!condition) return this;
            SmCriterion sm = new SmCriterion(LambdaFunctionUtil.getFieldName(column), value, CriteriaType.ge, connector);
            criterionList.add(sm);
            return this;
        }

        /**
         * 小于等于
         *
         * @param column
         * @param value
         * @return
         */
        public <R extends SerializableFunction<T, Object>> LambdaSmCriteriaBuild<T> le(Boolean condition, R column, Object value, CriteriaConnector connector) {
            if(!condition) return this;
            SmCriterion sm = new SmCriterion(LambdaFunctionUtil.getFieldName(column), value, CriteriaType.le, connector);
            criterionList.add(sm);
            return this;
        }

        /**
         * 大于
         *
         * @param column
         * @param value
         * @return
         */
        public <R extends SerializableFunction<T, Object>> LambdaSmCriteriaBuild<T> gt(Boolean condition, R column, Object value, CriteriaConnector connector) {
            if(!condition) return this;
            SmCriterion sm = new SmCriterion(LambdaFunctionUtil.getFieldName(column), value, CriteriaType.gt, connector);
            criterionList.add(sm);
            return this;
        }

        /**
         * 小于
         *
         * @param column
         * @param value
         * @return
         */
        public <R extends SerializableFunction<T, Object>> LambdaSmCriteriaBuild<T> lt(Boolean condition, R column, Object value, CriteriaConnector connector) {
            if(!condition) return this;
            SmCriterion sm = new SmCriterion(LambdaFunctionUtil.getFieldName(column), value, CriteriaType.lt, connector);
            criterionList.add(sm);
            return this;
        }

        /**
         * 模糊匹配
         *
         * @param column
         * @param value
         * @return
         */
        public <R extends SerializableFunction<T, Object>> LambdaSmCriteriaBuild<T> like(Boolean condition, R column, Object value, CriteriaConnector connector) {
            if(!condition) return this;
            SmCriterion sm = new SmCriterion(LambdaFunctionUtil.getFieldName(column), value, CriteriaType.like, connector);
            criterionList.add(sm);
            return this;
        }

        /**
         * 为空
         *
         * @param column
         * @return
         */
        public <R extends SerializableFunction<T, Object>> LambdaSmCriteriaBuild<T> isNull(Boolean condition, R column, CriteriaConnector connector) {
            if(!condition) return this;
            SmCriterion sm = new SmCriterion(LambdaFunctionUtil.getFieldName(column), null, CriteriaType.isNull, connector);
            criterionList.add(sm);
            return this;
        }

        /**
         * 不为空
         *
         * @param column
         * @return
         */
        public <R extends SerializableFunction<T, Object>> LambdaSmCriteriaBuild<T> isNotNull(Boolean condition, R column, CriteriaConnector connector) {
            if(!condition) return this;
            SmCriterion sm = new SmCriterion(LambdaFunctionUtil.getFieldName(column), null, CriteriaType.isNotNull, connector);
            criterionList.add(sm);
            return this;
        }


        /**
         * in
         *
         * @param column
         * @param value
         * @return
         */
        public <R extends SerializableFunction<T, Object>> LambdaSmCriteriaBuild<T> in(Boolean condition, R column, Object value, CriteriaConnector connector) {
            if(!condition) return this;
            SmCriterion sm = new SmCriterion(LambdaFunctionUtil.getFieldName(column), value, CriteriaType.in, connector);
            criterionList.add(sm);
            return this;
        }


        /**
         * 相等
         *
         * @param column
         * @param value
         * @return
         */
        public <R extends SerializableFunction<T, Object>> LambdaSmCriteriaBuild<T> eq(Boolean condition, R column, Object value) {
            if(!condition) return this;
            SmCriterion sm = new SmCriterion(LambdaFunctionUtil.getFieldName(column), value, CriteriaType.eq);
            criterionList.add(sm);
            return this;
        }

        /**
         * 大于等于
         *
         * @param column
         * @param value
         * @return
         */
        public <R extends SerializableFunction<T, Object>> LambdaSmCriteriaBuild<T> ge(Boolean condition, R column, Object value) {
            if(!condition) return this;
            SmCriterion sm = new SmCriterion(LambdaFunctionUtil.getFieldName(column), value, CriteriaType.ge);
            criterionList.add(sm);
            return this;
        }

        /**
         * 小于等于
         *
         * @param column
         * @param value
         * @return
         */
        public <R extends SerializableFunction<T, Object>> LambdaSmCriteriaBuild<T> le(Boolean condition, R column, Object value) {
            if(!condition) return this;
            SmCriterion sm = new SmCriterion(LambdaFunctionUtil.getFieldName(column), value, CriteriaType.le);
            criterionList.add(sm);
            return this;
        }

        /**
         * 大于
         *
         * @param column
         * @param value
         * @return
         */
        public <R extends SerializableFunction<T, Object>> LambdaSmCriteriaBuild<T> gt(Boolean condition, R column, Object value) {
            if(!condition) return this;
            SmCriterion sm = new SmCriterion(LambdaFunctionUtil.getFieldName(column), value, CriteriaType.gt);
            criterionList.add(sm);
            return this;
        }

        /**
         * 小于
         *
         * @param column
         * @param value
         * @return
         */
        public <R extends SerializableFunction<T, Object>> LambdaSmCriteriaBuild<T> lt(Boolean condition, R column, Object value) {
            if(!condition) return this;
            SmCriterion sm = new SmCriterion(LambdaFunctionUtil.getFieldName(column), value, CriteriaType.lt);
            criterionList.add(sm);
            return this;
        }

        /**
         * 模糊匹配
         *
         * @param column
         * @param value
         * @return
         */
        public <R extends SerializableFunction<T, Object>> LambdaSmCriteriaBuild<T> like(Boolean condition, R column, Object value) {
            if(!condition) return this;
            SmCriterion sm = new SmCriterion(LambdaFunctionUtil.getFieldName(column), value, CriteriaType.like);
            criterionList.add(sm);
            return this;
        }

        /**
         * 为空
         *
         * @param column
         * @return
         */
        public <R extends SerializableFunction<T, Object>> LambdaSmCriteriaBuild<T> isNull(Boolean condition, R column) {
            if(!condition) return this;
            SmCriterion sm = new SmCriterion(LambdaFunctionUtil.getFieldName(column), null, CriteriaType.isNull);
            criterionList.add(sm);
            return this;
        }

        /**
         * 不为空
         *
         * @param column
         * @return
         */
        public <R extends SerializableFunction<T, Object>> LambdaSmCriteriaBuild<T> isNotNull(Boolean condition, R column) {
            if(!condition) return this;
            SmCriterion sm = new SmCriterion(LambdaFunctionUtil.getFieldName(column), null, CriteriaType.isNotNull);
            criterionList.add(sm);
            return this;
        }

        /**
         * in
         *
         * @param column
         * @param value
         * @return
         */
        public <R extends SerializableFunction<T, Object>> LambdaSmCriteriaBuild<T> in(Boolean condition, R column, Object value) {
            if(!condition) return this;
            SmCriterion sm = new SmCriterion(LambdaFunctionUtil.getFieldName(column), value, CriteriaType.in);
            criterionList.add(sm);
            return this;
        }


        /**
         * 相等
         *
         * @param value
         * @return
         */
        public <R extends SerializableFunction<T, Object>> LambdaSmCriteriaBuild<T> eq(R column, Object value, CriteriaConnector connector) {
            return eq(true, column, value, connector);
        }

        /**
         * 相等
         *
         * @param value
         * @return
         */
        public <R extends SerializableFunction<T, Object>> LambdaSmCriteriaBuild<T> ge(R column, Object value, CriteriaConnector connector) {
            return ge(true, column, value, connector);
        }

        /**
         * 小于等于
         *
         * @param column
         * @param value
         * @return
         */
        public <R extends SerializableFunction<T, Object>> LambdaSmCriteriaBuild<T> le(R column, Object value, CriteriaConnector connector) {
            return le(true, column, value, connector);
        }

        /**
         * 大于
         *
         * @param column
         * @param value
         * @return
         */
        public <R extends SerializableFunction<T, Object>> LambdaSmCriteriaBuild<T> gt(R column, Object value, CriteriaConnector connector) {
            return gt(true, column, value, connector);
        }

        /**
         * 小于
         *
         * @param column
         * @param value
         * @return
         */
        public <R extends SerializableFunction<T, Object>> LambdaSmCriteriaBuild<T> lt(R column, Object value, CriteriaConnector connector) {
            return lt(true, column, value, connector);
        }

        /**
         * 模糊匹配
         *
         * @param column
         * @param value
         * @return
         */
        public <R extends SerializableFunction<T, Object>> LambdaSmCriteriaBuild<T> like(R column, Object value, CriteriaConnector connector) {
            return like(true, column, connector);
        }

        /**
         * 为空
         *
         * @param column
         * @return
         */
        public <R extends SerializableFunction<T, Object>> LambdaSmCriteriaBuild<T> isNull(R column, CriteriaConnector connector) {
            return isNull(true, column, connector);
        }

        /**
         * 不为空
         *
         * @param column
         * @return
         */
        public <R extends SerializableFunction<T, Object>> LambdaSmCriteriaBuild<T> isNotNull(R column, CriteriaConnector connector) {
            return isNotNull(true, column, connector);
        }


        /**
         * in
         *
         * @param column
         * @param value
         * @return
         */
        public <R extends SerializableFunction<T, Object>> LambdaSmCriteriaBuild<T> in(R column, Object value, CriteriaConnector connector) {
            return in(true, column, value, connector);
        }


        /**
         * 相等
         *
         * @param column
         * @param value
         * @return
         */
        public <R extends SerializableFunction<T, Object>> LambdaSmCriteriaBuild<T> eq(R column, Object value) {
            return eq(true, column, value);
        }

        /**
         * 大于等于
         *
         * @param column
         * @param value
         * @return
         */
        public <R extends SerializableFunction<T, Object>> LambdaSmCriteriaBuild<T> ge(R column, Object value) {
            return ge(true, column, value);
        }

        /**
         * 小于等于
         *
         * @param column
         * @param value
         * @return
         */
        public <R extends SerializableFunction<T, Object>> LambdaSmCriteriaBuild<T> le(R column, Object value) {
            return le(true, column, value);
        }

        /**
         * 大于
         *
         * @param column
         * @param value
         * @return
         */
        public <R extends SerializableFunction<T, Object>> LambdaSmCriteriaBuild<T> gt(R column, Object value) {
            return gt(true, column, value);
        }

        /**
         * 小于
         *
         * @param column
         * @param value
         * @return
         */
        public <R extends SerializableFunction<T, Object>> LambdaSmCriteriaBuild<T> lt(R column, Object value) {
            return lt(true, column, value);
        }

        /**
         * 模糊匹配
         *
         * @param column
         * @param value
         * @return
         */
        public <R extends SerializableFunction<T, Object>> LambdaSmCriteriaBuild<T> like(R column, Object value) {
            return like(true, column, value);
        }

        /**
         * 为空
         *
         * @param column
         * @return
         */
        public <R extends SerializableFunction<T, Object>> LambdaSmCriteriaBuild<T> isNull(R column) {
            return isNull(true, column);
        }

        /**
         * 不为空
         *
         * @param column
         * @return
         */
        public <R extends SerializableFunction<T, Object>> LambdaSmCriteriaBuild<T> isNotNull(R column) {
            return isNotNull(true, column);
        }

        /**
         * in
         *
         * @param column
         * @param value
         * @return
         */
        public <R extends SerializableFunction<T, Object>> LambdaSmCriteriaBuild<T> in(R column, Object value) {
            return in(true, column, value);
        }


        public <R extends SerializableFunction<T, Object>> LambdaSmCriteriaBuild<T> customerRetColumn(R column){
            this.customerRetColumn = new String[]{LambdaFunctionUtil.getFieldName(column)};
            return this;
        }

        public <R extends SerializableFunction<T, Object>> LambdaSmCriteriaBuild<T> customerRetColumn(R[] customerRetColumn){
            this.customerRetColumn = (String[])Arrays.stream(customerRetColumn).map(i -> LambdaFunctionUtil.getFieldName(i)).collect(Collectors.toList()).toArray();
            return this;
        }
    }

    public List<Object> getCriterionList() {
        return criterionList;
    }

    public String[] getCustomerRetColumn() {
        return customerRetColumn;
    }
}
